﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Controls;
using YJKArchUtils.Utils;
using YJKGeometryFuncs.CurveUtility;

namespace YJKRevitWallModule.WallModule.CreateWall
{
	public class JigLineOperator
	{
		public JigLineOperator(Autodesk.Revit.DB.Document inputDoc, DrawWallForm inputForm, ExternalCommandData commandData)
		{
			this.m_doc = inputDoc;
			this.thisForm = inputForm;
			this.thisTypeManager = new WallTypeManager(this.m_doc, this.thisForm.m_lstWallTypes, commandData);
		}

		public void ClearSelectPt()
		{
			this.m_nowPointIndex = -1;
			this.m_lstUsePt.Clear();
		}

		public void AddOnePoint(XYZ input, ref UseData inputUseData)
		{
			if (input != null)
			{
				if (0 < this.m_lstUsePt.Count && input.IsAlmostEqualTo(this.m_lstUsePt[this.m_lstUsePt.Count - 1]))
				{
					return;
				}
				this.m_lstUsePt.Add(input);
				this.m_nowPointIndex++;
				this.makeAndDrawNewCurve(ref inputUseData, true, false);
			}
		}

		public XYZ GetEndPoint()
		{
			if (0 >= this.m_lstUsePt.Count)
			{
				return null;
			}
			return this.m_lstUsePt[this.m_lstUsePt.Count - 1];
		}

		private List<Curve> GetNormalLineBoundryCurves(UseData useData, XYZ startPoint, XYZ endPoint, ref Curve cv)
		{
			double num = 0.4;
			List<Curve> list = new List<Curve>();
			this.OffsetCvByLocationType(useData, startPoint, endPoint, ref cv);
			Line.CreateBound(startPoint, endPoint);
			if (useData.wallTypeId == ElementId.InvalidElementId)
			{
				num = double.Parse(useData.strLeftKeepWarmWidth) + double.Parse(useData.strWallWidth) + double.Parse(useData.strRightKeepWarmWidth);
			}
			else
			{
				try
				{
					num = (this.m_doc.GetElement(useData.wallTypeId) as WallType).Width;
				}
				catch (Exception)
				{
				}
			}
			Line input = this.CreateSameOffset(cv, num / 2.0, XYZ.BasisZ) as Line;
			Line line = this.CreateSameOffset(input, 0.0, XYZ.BasisZ) as Line;
			Line line2 = this.CreateSameOffset(input, num, XYZ.BasisZ.Negate()) as Line;
			list.Add(Line.CreateBound(line2.GetEndPoint(0), line.GetEndPoint(0)));
			list.Add(line);
			list.Add(Line.CreateBound(line.GetEndPoint(1), line2.GetEndPoint(1)));
			list.Add(this.CreateReversedUtility(line2));
			return list;
		}

		private Curve CreateSameOffset(Curve input, double offsetDist, XYZ normal)
		{
			if (normal.Z > 0.0)
			{
				return CurveUtility.CreateOffsetCurve(input, offsetDist);
			}
			return CurveUtility.CreateOffsetCurve(input, -offsetDist);
		}

		private Curve CreateReversedUtility(Curve input)
		{
			try
			{
				if (input is Line)
				{
					return Line.CreateBound(input.GetEndPoint(1), input.GetEndPoint(0));
				}
				if (input is Arc)
				{
					XYZ center = (input as Arc).Center;
					return Arc.Create(input.GetEndPoint(1), input.GetEndPoint(0), center);
				}
			}
			catch (Exception)
			{
			}
			return null;
		}

		private void makeAndDrawNewCurve(ref UseData inputUseData, bool ifDraw = true, bool ifIsEnd = false)
		{
			Curve curve = null;
			List<Curve> list = new List<Curve>();
			List<DetailCurve> list2 = new List<DetailCurve>();
			if (!ifIsEnd)
			{
				if (0 >= this.m_nowPointIndex)
				{
					return;
				}
				if (this.m_lstUsePt.Count > 2)
				{
					this.m_lstUsePt.RemoveAt(0);
				}
				this.thisTypeManager.SetUseData(inputUseData);
				if (inputUseData.wallTypeId == ElementId.InvalidElementId)
				{
					WallType wallType = this.thisTypeManager.CreateNewWallType();
					if (wallType == null)
					{
						this.ClearSelectPt();
						YJKMessageBox.Show("新建墙体类型失败,请检查面层设置是否正确!");
						return;
					}
					inputUseData.wallTypeId = wallType.Id;
				}
				list.AddRange(this.GetNormalLineBoundryCurves(inputUseData, this.m_lstUsePt[0], this.m_lstUsePt[1], ref curve));
				inputUseData.line = (curve as Line);
				inputUseData.direction = this.m_lstUsePt[1].Add(-this.m_lstUsePt[0]).Normalize();
				Transaction transaction = new Transaction(this.m_doc, "creat");
				transaction.Start();
				try
				{
					foreach (Curve curve2 in list)
					{
						DetailCurve item = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, curve2);
						list2.Add(item);
					}
					transaction.Commit();
					this.m_lstMakedDetailCurves.Add(list2);
					return;
				}
				catch (Exception)
				{
					transaction.RollBack();
					throw;
				}
				return;
			}
		}

		private void OffsetCvByLocationType(UseData useData, XYZ startPoint, XYZ endPoint, ref Curve cv)
		{
			double num = 0.0;
			double num2 = 0.0;
			double num3 = 0.0;
			double num4 = 0.0;
			double num5 = 0.0;
			if (useData.wallTypeId == ElementId.InvalidElementId)
			{
				num = Common.MMToFeet(double.Parse(useData.strLeftKeepWarmWidth) + double.Parse(useData.strWallWidth) + double.Parse(useData.strRightKeepWarmWidth));
			}
			else
			{
				try
				{
					WallType wallType = this.m_doc.GetElement(useData.wallTypeId) as WallType;
					this.GetLayerThickness(wallType, ref num2, ref num3, ref num4, ref num5);
					num = wallType.Width;
				}
				catch (Exception)
				{
				}
			}
			Curve curve = CurveUtility.CreateOffsetCurve(Line.CreateBound(startPoint, endPoint), num / 2.0);
			if (useData.location == LocationCv.WallCenter)
			{
				cv = CurveUtility.CreateOffsetCurve(curve, -num / 2.0);
				return;
			}
			double num6;
			if (useData.location != LocationCv.CoreCenter)
			{
				if (useData.location == LocationCv.CoreLayerOuter)
				{
					if (useData.wallTypeId == ElementId.InvalidElementId && useData.strLeftKeepWarmWidth == "0")
					{
						cv = curve;
						return;
					}
					if (useData.wallTypeId == ElementId.InvalidElementId && useData.strLeftKeepWarmWidth != "0")
					{
						num6 = Common.MMToFeet(double.Parse(useData.strLeftKeepWarmWidth));
						cv = CurveUtility.CreateOffsetCurve(curve, -num6);
						return;
					}
					if (useData.wallTypeId != ElementId.InvalidElementId)
					{
						cv = CurveUtility.CreateOffsetCurve(curve, -num2);
						return;
					}
				}
				else if (useData.location == LocationCv.CoreLayerInner)
				{
					if (useData.wallTypeId == ElementId.InvalidElementId && useData.strRightKeepWarmWidth == "0")
					{
						cv = CurveUtility.CreateOffsetCurve(curve, -num);
						return;
					}
					if (useData.wallTypeId == ElementId.InvalidElementId && useData.strRightKeepWarmWidth != "0")
					{
						cv = CurveUtility.CreateOffsetCurve(curve, -(num - Common.MMToFeet(double.Parse(useData.strRightKeepWarmWidth))));
						return;
					}
					if (useData.wallTypeId != ElementId.InvalidElementId)
					{
						cv = CurveUtility.CreateOffsetCurve(curve, -num3);
						return;
					}
				}
				else if (useData.location == LocationCv.SurfaceLayerInner)
				{
					if (useData.wallTypeId == ElementId.InvalidElementId)
					{
						cv = CurveUtility.CreateOffsetCurve(curve, -num);
						return;
					}
					cv = CurveUtility.CreateOffsetCurve(curve, -num5);
					return;
				}
				else if (useData.location == LocationCv.SurfaceLayerOuter)
				{
					if (useData.wallTypeId == ElementId.InvalidElementId)
					{
						cv = curve;
						return;
					}
					cv = CurveUtility.CreateOffsetCurve(curve, -num4);
				}
				return;
			}
			if (useData.wallTypeId == ElementId.InvalidElementId)
			{
				num6 = Common.MMToFeet(double.Parse(useData.strLeftKeepWarmWidth) + double.Parse(useData.strWallWidth) / 2.0);
				cv = CurveUtility.CreateOffsetCurve(curve, -num6);
				return;
			}
			num6 = num2 + (num3 - num2) / 2.0;
			cv = CurveUtility.CreateOffsetCurve(curve, -num6);
		}

		private void GetLayerThickness(WallType tmpWallType, ref double dOuterCoreThickness, ref double dInnerCoreThickness, ref double dOuterSurfaceLayerThickness, ref double dInnerSurfaceLayerThickness)
		{
			int num = 0;
			bool flag = false;
			if (tmpWallType.GetCompoundStructure() != null)
			{
				int firstCoreLayerIndex = tmpWallType.GetCompoundStructure().GetFirstCoreLayerIndex();
				int lastCoreLayerIndex = tmpWallType.GetCompoundStructure().GetLastCoreLayerIndex();
				IList<CompoundStructureLayer> layers = tmpWallType.GetCompoundStructure().GetLayers();
				foreach (CompoundStructureLayer compoundStructureLayer in layers)
				{
					dInnerCoreThickness += compoundStructureLayer.Width;
					if (num == lastCoreLayerIndex)
					{
						break;
					}
					if (num < firstCoreLayerIndex)
					{
						dOuterCoreThickness += compoundStructureLayer.Width;
					}
					num++;
				}
				foreach (CompoundStructureLayer compoundStructureLayer2 in layers)
				{
					if ((int)compoundStructureLayer2.Function == 4)
					{
						flag = true;
						break;
					}
					dOuterSurfaceLayerThickness += compoundStructureLayer2.Width;
					if (!flag)
					{
						dOuterSurfaceLayerThickness = 0.0;
					}
				}
				foreach (CompoundStructureLayer compoundStructureLayer3 in layers)
				{
					dInnerSurfaceLayerThickness += compoundStructureLayer3.Width;
					if ((int)compoundStructureLayer3.Function == 5)
					{
						break;
					}
				}
			}
		}

		public void deleteDetailCures()
		{
			Transaction transaction = new Transaction(this.m_doc, "delete");
			transaction.Start();
			try
			{
				foreach (List<DetailCurve> list in this.m_lstMakedDetailCurves)
				{
					foreach (DetailCurve detailCurve in list)
					{
						this.m_doc.Delete(detailCurve.Id);
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			this.m_lstMakedDetailCurves.Clear();
		}

		private Document m_doc;

		private List<XYZ> m_lstUsePt = new List<XYZ>();

		public List<Curve> m_lstTempCurve = new List<Curve>();

		private List<DetailCurve> m_lstTempDCurve = new List<DetailCurve>();

		private int m_nowPointIndex = -1;

		private List<List<DetailCurve>> m_lstMakedDetailCurves = new List<List<DetailCurve>>();

		private DrawWallForm thisForm;

		private WallTypeManager thisTypeManager;
	}
}
